using System;
using System.Collections.Generic;
using System.Text;
using OpenTK.Math;

namespace Dogfight2008.Common
{
  public class Triangle
  {
    public readonly Vector3 P1,P2,P3;

    public Triangle(Vector3 p1, Vector3 p2, Vector3 p3)
    {
      P1 = p1;
      P2 = p2;
      P3 = p3;
    }

    public IntersectionResult Intersect(Ray r)
    {
      Vector3 p2p1 = P2 - P1;
      Vector3 p3p1 = P3 - P1;
      Vector3 triNormal = Vector3.Cross(p2p1, p3p1);
      triNormal.Normalize();
      float dot = Vector3.Dot(r.Direction, triNormal);
      if (Calc.AlmostZero(dot))
        return IntersectionResult.NoIntersection;
      else
      {
        float d = Vector3.Dot(triNormal, P1);
        float np4 = Vector3.Dot(triNormal, r.Origin);
        float nv = Vector3.Dot(triNormal, r.Direction);
        float t = (d - np4) / nv;

        Vector3 q = r.Origin + r.Direction * t;

        float a = Vector3.Dot(Vector3.Cross(p2p1, q - P1), triNormal);
        float b = Vector3.Dot(Vector3.Cross(P3 - P2, q - P2), triNormal);
        float c = Vector3.Dot(Vector3.Cross(P1 - P3, q - P3), triNormal);
        if (a >= 0 && b >= 0 && c >= 0)
          return IntersectionResult.Interects(t);
        else
          return IntersectionResult.NoIntersection;
      }
    }

    public override bool Equals(object obj)
    {
      Triangle rhs = obj as Triangle;
      if (rhs == null)
        return false;

      return Calc.AlmostEqual(P1, rhs.P1) && Calc.AlmostEqual(P2, rhs.P2) && Calc.AlmostEqual(P3, rhs.P3);
    }

    public override int GetHashCode()
    {
      unchecked
      {
        return P1.GetHashCode() + P2.GetHashCode() + P3.GetHashCode();
      }
    }

    public Vector3 Normal
    {
      get
      {
        Vector3 n = Vector3.Cross(P2-P1,P3-P1);
        n.NormalizeFast();
        return n;
      }
    }
  }
}
